#include <PA9.h>
#include "charutil.h"

#include "chardata.h"

#define NOT_SUPPORTED	-1
#define HZ_NUM			6763
#define SYM_NUM			717
#define CODE_NUM		(HZ_NUM+SYM_NUM)
extern void utf82Unicode(const char *srcstr,u16 *dststr)
{
	while(*srcstr!=0){
		u16 b0=(byte)srcstr[0],b1=(byte)srcstr[1],b2=(byte)srcstr[2];
		u16 uc;
		
		if(b0<0x80){
			uc=b0;
			srcstr++;
		}else{
			if((b0&0xe0)==0xc0){ // 0b 110. ....
				uc=((b0&~0xe0)<<6)+((b1&~0xc0)<<0);
				srcstr+=2;
			}else{
				if((b0&0xf0)==0xe0){ // 0b 1110 ....
					uc=((b0&~0xf0)<<12)+((b1&~0xc0)<<6)+((b2&~0xc0)<<0);
					srcstr+=3;
				}else{
					uc=(u16)'?';
					srcstr+=4;
				}
			}
		}
		
		//if(FontPro_Exists(uc)==false) uc=(u16)'?';
		
		*dststr=uc;
		dststr++;
	}
	
	*dststr=(u16)0;
}

/****************************************************************************
* NAME:		binarySearch
* PURPOSR:	perform binary search in uint16 array
* ENTRY:	table	- point to uint16 array
*		tablen	- length of array
*		code	- word to search
* EXIT:		int16 - index of object, -1 for no match
* AUTHOR: 	lvjie November 18, 2003
****************************************************************************/
int binarySearch(const u16 *table, 
				 u16 tablen, 
				 u16 code)
{
	u16 head,tail,middle;
	
	head = 0;
	tail = tablen-1;
	if ((code < table[head])||(code > table[tail]))
		return(-1);
	
	while (head <= tail)
	{
		middle = (head+tail)/2;
		if (code == table[middle])
			return (middle);
		else if (code > table[middle])
			head = middle+1;
		else
			tail = middle-1;
	}
	
	return (NOT_SUPPORTED);
}

/* convert unicode word to gb2312 word. 
return ?? if unsupported */
unsigned short uc2gbc(unsigned short uc)
{
	int index = binarySearch(uniAUnicode, CODE_NUM, uc);
	
	if ( index == NOT_SUPPORTED ) {
		return 0x3f3f;	/* ?? */
	}
	else {
		return uniAGbkcode[index];
	}
}

/****************************************************************************
* NAME:		uni2gb
* PURPOSR:	Convert unicode string to gbk string
*			the byte order of unicode MUST be consistent with underlying CPU
*			the two-byte code in GBK is always big-endian
* ENTRY:	unistr	unicode string
*			gbbuf	output buffer
*			buflen	length of buffer
* EXIT:		length of gbk string
****************************************************************************/
extern void uni2gb(const u16 *unistr, char *gbbuf)
{   
	u16 t;
	while ( *unistr ) {
		if ( *unistr < 0x80 ) {
			*gbbuf++ = (char)(*unistr);
		}
		else {
			/* gbk-code is big-endian */
			t = uc2gbc(*unistr);
			*gbbuf++ = (u8)( t >> 8 );
			*gbbuf++ = (u8)( t & 0xff );
		}
		unistr++;
	}
	
	*gbbuf = '\0';
}


/*
*/
extern unsigned short getuni(unsigned short i)
{
	return uniAGbkcode[i];
}

extern void uni2gbchar(u16 unistr,unsigned char *gbbuf)
{   
	u16 t=0;
	
	/* gbk-code is big-endian */
	t = uc2gbc(unistr);
	*gbbuf++ = (u8)( t >> 8 );
	*gbbuf   = (u8)( t & 0xff );
	
}


